package util

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type Mysql struct {
	*gorm.DB
}

func NewMysql(link string) (Db, error) {
	db, err := gorm.Open(mysql.Open(link), &gorm.Config{})
	if err != nil {
		return nil, err
	}
	return &Mysql{db}, nil
}

type (
	tableScan struct {
		Name string `json:"name"`
		Desc string `json:"desc"`
	}
	fieldScan struct {
		TableName     string `json:"table_name"`
		ColumnName    string `json:"column_name"`
		DataType      string `json:"data_type"`
		ColumnType    string `json:"column_type"`
		ColumnComment string `json:"column_comment"`
	}
)

func (s *Mysql) GetTables() ([]*Table, error) {
	var tableList []*tableScan
	err := s.DB.Raw("SELECT TABLE_NAME as name,TABLE_COMMENT as `desc` FROM information_schema.tables where TABLE_SCHEMA=?", s.Migrator().CurrentDatabase()).
		Scan(&tableList).Error
	if err != nil {
		return nil, err
	}

	var fieldList []*fieldScan
	err = s.DB.Raw("SELECT TABLE_NAME as table_name,COLUMN_NAME as column_name,DATA_TYPE as data_type,COLUMN_TYPE as column_type,COLUMN_COMMENT as column_comment FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = ? ORDER BY TABLE_NAME,ORDINAL_POSITION ", s.Migrator().CurrentDatabase()).
		Scan(&fieldList).Error
	if err != nil {
		return nil, err
	}

	var (
		tableMap = make(map[string]*Table)
		result   = []*Table{}
	)
	for _, table := range tableList {
		t := &Table{
			Name: table.Name,
			Desc: table.Desc,
		}
		tableMap[table.Name] = t
		result = append(result, t)
	}

	for _, field := range fieldList {
		if table, ok := tableMap[field.TableName]; ok {
			table.Fields = append(table.Fields, &Field{
				Name: field.ColumnName,
				Type: field.DataType,
				Desc: field.ColumnComment,
			})
		}
	}
	return result, err
}
